﻿/*
* 时间：2019年7月 
* 作者：潘意
* 
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.Collections;
using System.Drawing;
using System.Drawing.Design;
using System.Reflection;
using System.IO;
using EMRView;
using HC.View;
using EMRView.Extensions.HCAttribute;
using System.Threading;

namespace EMRView.Extensions.Command
{
    [ProvideProperty("Command", typeof(System.ComponentModel.Component)),
     ToolboxBitmap(typeof(HCCommandControl)),
     ToolboxItem(true)]
    public class HCCommandControl : System.ComponentModel.Component, IExtenderProvider, ISupportInitialize
    {
        private static readonly Dictionary<string, BaseCommand> _commands = new Dictionary<string, BaseCommand>();
        private readonly Hashtable _components = new Hashtable();
        private readonly IContainer _container;
        private HCEmrView _view;

        public HCCommandControl()
        {
        }

        public HCCommandControl(IContainer container)
        {
            container.Add(this);
            _container = container;
            _components = new Hashtable();
        }

        public int ControlCount
        {
            get
            {
                return _components.Count;
            }
        }

        public HCEmrView HCEmrView
        {
            set
            {
                _view = value;
                _view.OnCaretChange += (s, e) =>
                {
                    if (_view.CurStyleNo >= 0 && _view.CurParaNo >= 0)
                    {
                        try
                        {
                            foreach (System.ComponentModel.Component item in _components.Keys)
                            {
                                var baseCommand = _components[item] as BaseCommand;
                                if (item is ToolStripButton)
                                {
                                    var btn = item as ToolStripButton;
                                    var attr = baseCommand.GetType().GetCustomAttributes(false);
                                    foreach (var a in attr)
                                    {
                                        if (a is CommandAttribute)
                                        {
                                            var commandA = a as CommandAttribute;
                                            ParaAlignHorz vAlignHorz = _view.Style.ParaStyles[_view.CurParaNo].AlignHorz;
                                            switch (commandA.CommandName)
                                            {
                                                case "Bold":
                                                    btn.Checked = _view.Style.TextStyles[_view.CurStyleNo].FontStyles.Contains((byte)HCFontStyle.tsBold);
                                                    break;
                                                case "Italic":
                                                    btn.Checked = _view.Style.TextStyles[_view.CurStyleNo].FontStyles.Contains((byte)HCFontStyle.tsItalic);
                                                    break;
                                                case "Underline":
                                                    btn.Checked = _view.Style.TextStyles[_view.CurStyleNo].FontStyles.Contains((byte)HCFontStyle.tsUnderline);
                                                    break;
                                                case "StrikeOut":
                                                    btn.Checked = _view.Style.TextStyles[_view.CurStyleNo].FontStyles.Contains((byte)HCFontStyle.tsStrikeOut);
                                                    break;
                                                case "Superscript":
                                                    btn.Checked = _view.Style.TextStyles[_view.CurStyleNo].FontStyles.Contains((byte)HCFontStyle.tsSuperscript);
                                                    break;
                                                case "Subscript":
                                                    btn.Checked = _view.Style.TextStyles[_view.CurStyleNo].FontStyles.Contains((byte)HCFontStyle.tsSubscript);
                                                    break;
                                                case "AlignCenter":
                                                    btn.Checked = vAlignHorz == ParaAlignHorz.pahCenter;
                                                    break;
                                                case "AlignLeft":
                                                    btn.Checked = vAlignHorz == ParaAlignHorz.pahLeft;
                                                    break;
                                                case "AlignRight":
                                                    btn.Checked = vAlignHorz == ParaAlignHorz.pahRight;
                                                    break;
                                                case "AlignJustify":
                                                    btn.Checked = vAlignHorz == ParaAlignHorz.pahJustify;
                                                    break;
                                                case "AlignScatter":
                                                    btn.Checked = vAlignHorz == ParaAlignHorz.pahScatter;
                                                    break;
                                                default:
                                                    break;
                                            }
                                            break;
                                        }
                                    }
                                }
                                if (item is ToolStripComboBox)
                                {
                                    var cmb = item as ToolStripComboBox;
                                    var attr = baseCommand.GetType().GetCustomAttributes(false);
                                    foreach (var a in attr)
                                    {
                                        if (a is CommandAttribute)
                                        {
                                            var commandA = a as CommandAttribute;
                                            switch (commandA.CommandName)
                                            {
                                                case "Font":
                                                    cmb.SelectedIndex = cmb.Items.IndexOf(_view.Style.TextStyles[_view.CurStyleNo].Family);
                                                    break;
                                                case "FontSize":
                                                    cmb.SelectedIndex = cmb.Items.IndexOf(HC.View.HC.GetFontSizeStr(_view.Style.TextStyles[_view.CurStyleNo].Size));
                                                    break;
                                                default:
                                                    break;
                                            }
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception)
                        {
                        }
                    }
                };
                _view.OnZoomChanged += (s, e) =>
                {
                    foreach (System.ComponentModel.Component item in _components.Keys)
                    {
                        var baseCommand = _components[item] as BaseCommand;
                        if (item is ToolStripComboBox)
                        {
                            var cmb = item as ToolStripComboBox;
                            var attr = baseCommand.GetType().GetCustomAttributes(false);
                            foreach (var a in attr)
                            {
                                if (a is CommandAttribute)
                                {
                                    var commandA = a as CommandAttribute;
                                    switch (commandA.CommandName)
                                    {
                                        case "Zoom":
                                            string vZoom = Math.Round(_view.Zoom * 100).ToString();
                                            int vIndex = cmb.Items.IndexOf(vZoom);
                                            if (vIndex < 0)
                                            {
                                                cmb.Items[cmb.Items.Count - 1] = vZoom;
                                                vIndex = cmb.Items.Count - 1;
                                            }

                                            cmb.SelectedIndex = vIndex;
                                            break;
                                        default:
                                            break;
                                    }
                                    break;
                                }
                            }
                        }
                    }
                };
            }
        }

        /// <summary>
        /// 开始初始化
        /// </summary>
        public void BeginInit()
        {
            try
            {
                var baseCommand = typeof(BaseCommand);
                var list = System.AppDomain.CurrentDomain.GetAssemblies();
                foreach (var assembly in list)
                {
                    List<Type> types = new List<Type>();
                    Type[] typeArray;
                    try
                    {
                        typeArray = assembly.GetTypes();
                    }
                    catch (Exception ex)
                    {
                        continue;
                    }
                    for (int j = 0; j < typeArray.Length; j++)
                    {
                        var t = typeArray[j];

                        if (t.Name == "FontCommand")
                        {

                        }
                        if (t.BaseType != null)
                        {
                            if (baseCommand == t.BaseType)
                            {
                                types.Add(t);
                            }
                        }
                    }
                    foreach (var type in types)
                    {
                        var attributes = type.GetCustomAttributes(false);
                        foreach (var attr in attributes)
                        {
                            if (attr is CommandAttribute)
                            {
                                var a = (EMRView.Extensions.HCAttribute.CommandAttribute)attr;
                                _commands.TryGetValue(a.CommandName, out BaseCommand command);
                                if (command == null)
                                {
                                    _commands.Add(a.CommandName, System.Activator.CreateInstance(type) as BaseCommand);
                                }
                            }
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        [DefaultValue(""),]
        [Editor(typeof(HCCommandsEditor), typeof(UITypeEditor))]
        public string GetCommand(System.ComponentModel.Component control)
        {
            BaseCommand command = (BaseCommand)_components[control];
            if (command == null)
            {
                return "";
            }
            var attributes = command.GetType().GetCustomAttributes(true);
            foreach (var attr in attributes)
            {
                if (attr is CommandAttribute)
                {
                    var a = attr as CommandAttribute;
                    return a.CommandName;
                }
            }
            return "";
        }

        [Editor(typeof(HCCommandsEditor), typeof(UITypeEditor))]
        public void SetCommand(System.ComponentModel.Component component, object command)
        {
            if (command is string)
            {
                if (string.IsNullOrEmpty(command as string))
                {
                    _components.Remove(component);
                    if (component is ToolStripComboBox)
                    {
                        var cmb = component as ToolStripComboBox;
                        cmb.Items.Clear();
                    }
                }
                else
                {
                    var commandObj = _commands[command.ToString()];
                    if (!this.DesignMode)
                    {
                        commandObj.InitControl(component);
                    }
                    _components.Add(component, commandObj);
                    return;
                }
            }
            else if (command is BaseCommand)
            {
                if (command == null)
                {
                    _components.Remove(component);
                }
                else
                {
                    var com = command as BaseCommand;
                    var attributes = command.GetType().GetCustomAttributes(false);
                    _components[component] = command;
                    foreach (var attr in attributes)
                    {
                        if (attr is CommandAttribute)
                        {
                            var a = (CommandAttribute)attr;
                            if (component is ToolStripButton)
                            {
                                var btn = component as ToolStripButton;
                                btn.Image = com.CommandIcon?.ToBitmap();
                                btn.Text = a.CommandExplain;
                            }
                            if (component is ToolStripComboBox)
                            {
                                var cmb = component as ToolStripComboBox;
                            }
                        }
                    }
                }
            }

        }

        public bool CanExtend(object extendee)
        {
            if (extendee is System.ComponentModel.Component)
            {
                return true;
            }
            return false;
        }

        public void EndInit()
        {
            Thread thread = new Thread(() =>
              {
                  foreach (System.ComponentModel.Component item in _components.Keys)
                  {
                      var baseCommand = _components[item] as BaseCommand;
                      if (item is ToolStripButton)
                      {
                          var btn = item as ToolStripButton;
                          btn.Click += (s, e) =>
                          {
                              if (_view == null)
                              {
                                  MessageBox.Show("请在页面中绑定命令控件的HCEmrView属性", "命令执行提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                  return;
                              }
                              baseCommand.Execute(_view, false, null);

                          };
                      }
                      if (item is ToolStripComboBox)
                      {
                          var cmb = item as ToolStripComboBox;
                          cmb.DropDownClosed += (s, e) =>
                          {
                              if (_view == null)
                              {
                                  MessageBox.Show("请在页面中绑定命令控件的HCEmrView属性", "命令执行提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                  return;
                              }
                              if (cmb.SelectedItem != null)
                              {
                                  baseCommand.Execute(_view, false, cmb.SelectedItem.ToString());
                              }
                          };
                          cmb.SelectedIndexChanged += (s, e) =>
                          {
                              if (_view == null)
                              {
                                  MessageBox.Show("请在页面中绑定命令控件的HCEmrView属性", "命令执行提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                  return;
                              }
                              if (cmb.SelectedItem != null)
                              {
                                  baseCommand.Execute(_view, false, cmb.SelectedItem.ToString());
                              }
                          };
                      }
                  }
              });
            thread.Start();
        }

        private Image GetControlIconResources(string imageResourcesPath)
        {
            try
            {
                Assembly assem = this.GetType().Assembly;
                foreach (string resourceName in assem.GetManifestResourceNames())
                {
                    MessageBox.Show(imageResourcesPath);
                    Stream stream = assem.GetManifestResourceStream(imageResourcesPath);
                    MessageBox.Show(stream == null ? "空" : stream.ToString());
                    return EMRView.Extensions.Properties.HCResource.Save32;//new Bitmap(stream);
                }
                return null;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return null;
            }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        internal static object ExecuteCommand(HCEmrView view, string commandName, bool showUI, object parameter)
        {
            return _commands[commandName].Execute(view, showUI, parameter);
        }


    }
}
